#include "Dispatch.h"

#include "Init.h"
#include "Utils.h"
#include "HideFolder.h"

#pragma alloc_text(PAGE, FilterDispatchCreate)

NTSTATUS FilterDispatchCreate(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIRP)
{
    PFILE_HIDING_FILTER_DEVICE_EXTENSION pFilterDeviceExt = (PFILE_HIDING_FILTER_DEVICE_EXTENSION)pDeviceObject->DeviceExtension;

    PAGED_CODE();

    return PassThroughIRP(pIRP, pFilterDeviceExt->pNextLowerDevice);
}

#pragma alloc_text(PAGE, FilterDispatchClose)

NTSTATUS FilterDispatchClose(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIRP)
{
    PFILE_HIDING_FILTER_DEVICE_EXTENSION pFilterDeviceExt = (PFILE_HIDING_FILTER_DEVICE_EXTENSION)pDeviceObject->DeviceExtension;

    PAGED_CODE();

    return PassThroughIRP(pIRP, pFilterDeviceExt->pNextLowerDevice);
}

#pragma alloc_text(PAGE, FilterDispatchDirectoryControl)

NTSTATUS FilterDispatchDirectoryControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIRP)
{
    PFILE_HIDING_FILTER_DEVICE_EXTENSION pFilterDeviceExt = (PFILE_HIDING_FILTER_DEVICE_EXTENSION)pDeviceObject->DeviceExtension;
    PIO_STACK_LOCATION pIOStack = IoGetCurrentIrpStackLocation(pIRP);

    PAGED_CODE();

    if(IRP_MN_QUERY_DIRECTORY != pIOStack->MinorFunction)
    {
        return PassThroughIRP(pIRP, pFilterDeviceExt->pNextLowerDevice);
    }

    switch (pIOStack->Parameters.QueryDirectory.FileInformationClass)
    {
        case FileBothDirectoryInformation:
        {
            NTSTATUS ntStatus = STATUS_SUCCESS;

            ntStatus = WaitForIRPCompletion(pFilterDeviceExt->pNextLowerDevice, pIRP);

            if (NT_SUCCESS(ntStatus) && NT_SUCCESS(pIRP->IoStatus.Status))
            {
                PFILE_OBJECT pFileObject = pIOStack->FileObject;
                PFILE_BOTH_DIR_INFORMATION pFileBothDirInfoHead = (PFILE_BOTH_DIR_INFORMATION)pIRP->UserBuffer;

                ntStatus = CheckFolderContentAndHideIfNeed(pFileObject,
                                                           pFileBothDirInfoHead,
                                                           pIOStack->Parameters.QueryDirectory.Length,
                                                           BooleanFlagOn(pIOStack->Flags, SL_RESTART_SCAN),
                                                           BooleanFlagOn(pIOStack->Flags, SL_RETURN_SINGLE_ENTRY));

                if (STATUS_NO_SUCH_FILE == ntStatus)
                {
                    return SetStatusAndCompleteIRP(pIRP, STATUS_NO_SUCH_FILE, 0, IO_NO_INCREMENT);
                }
            }

            return CompleteIRP(pIRP, IO_NO_INCREMENT);
        }
        default:
        {
            break;
        }
    }

    return PassThroughIRP(pIRP, pFilterDeviceExt->pNextLowerDevice);
}
